﻿/*======================================================================
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
========================================================================*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Xml.Linq;
using BlueCurve.Common;
using BlueCurve.IRemoteOperations;

namespace Scheduler.Remoting
{
    /// <summary>
    /// Service wcF
    /// </summary>
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]
    public class Tcpservice : IWebScheduler
    {
        #region 'Events'

        /// <summary>
        /// Evenement de changement du temps avant de recontacter un serveur
        /// </summary>
        public delegate void ChangeHostWaitTimeEventHandler(object sender, Eventdata e);
        public static event ChangeHostWaitTimeEventHandler _ChangeHostWaitTime;
        /// <summary>
        /// Renvoie toutes les priotités d'un fichier
        /// </summary>
        public delegate string GetAllPriorityEventHandler(object sender, EventArgs e);
        public static event GetAllPriorityEventHandler _GetAllPriority;
        /// <summary>
        /// Evenement de demande de la priorité d'un fichier
        /// </summary>
        public delegate int GetPriorityEventHandler(object sender, Eventdata e);
        public static event GetPriorityEventHandler _GetPriority;
        /// <summary>
        /// Evenement d'ajout de liens à mettre à jour
        /// </summary>
        public delegate void LinkToUpdateEventHandler(object sender, Eventdata e);
        public static event LinkToUpdateEventHandler _LinkToUpdate;
        /// <summary>
        /// Evenement de définition de la priorité d'un fichier
        /// </summary>
        public delegate void SetPriorityEventHandler(object sender, Eventdata e);
        public static event SetPriorityEventHandler _SetPriority;
        /// <summary>
        /// Evenement de redemarrage de l'application
        /// </summary>
        public static event EventHandler _RestartApplication;
        /// <summary>
        /// Evenement d'arret de l'application
        /// </summary>
        public static event EventHandler _StopApplication;

        #endregion
        






        #region IWebScheduler Membres

        /// <summary>
        /// Change le temps d'attente avant de recontacter un serveur
        /// </summary>
        /// <param name="waitime">Nouveau temps d'attente</param>
        [OperationBehavior]
        public void ChangeHostWaitTime(int waitime)
        {
            _ChangeHostWaitTime("", new Eventdata() { waitime = waitime });
        }

        /// <summary>
        /// Obtient une copie XML des priorités des liens à mettre a jour
        /// </summary>
        /// <returns>string</returns>
        [OperationBehavior]
        public string GetAllPriority()
        {
            return _GetAllPriority("", EventArgs.Empty);
        }

        /// <summary>
        /// Obtient la priorité d'un lien
        /// </summary>
        /// <param name="key">lien</param>
        /// <returns>uint</returns>
        [OperationBehavior]
        public int GetPriority(string key)
        {
            return _GetPriority("", new Eventdata() { link = key });
        }

        /// <summary>
        /// Nouveaux liens à mettre a jour
        /// </summary>
        /// <param name="links">links (xml)</param>
        [OperationBehavior]
        public void LinkToUpdate(string links)
        {
            _LinkToUpdate("", new Eventdata() { links = links });
        }

        /// <summary>
        /// Obtient une liste de liens à télécharger
        /// </summary>
        /// <returns>string</returns>
        [OperationBehavior]
        public string SendQueue()
        {
            try
            {
                CommonFunctions common = new CommonFunctions();
                StringBuilder strb = new StringBuilder();
                List<object> items = new List<object>();

                using (SchedulerdbDataContext database = new SchedulerdbDataContext())
                {
                    Nullable<int> hoststoupdate = database.CountAvailableHostsToUpdate();
                    if (hoststoupdate == null)
                        return null;

                    if (hoststoupdate.Value > 0)
                    {
                        List<GetDocumentsToUpdateResult> result = database.GetDocumentsToUpdate().ToList(); ;

                        if (result.Count == 0)
                            return null;

                        var x = from i in result
                                select new
                                {
                                    Link = i.LINK,
                                    Lastupdate = i.LASTUPDATE,
                                    Lastmodified = i.LASTMODIFIED,
                                    Reindextime = i.REINDEXTIME
                                };

                        foreach (var v in x)
                        {
                            items.Add(new XElement("document",
                                      new XElement("url", new XCData(v.Link)),
                                      new XElement("state", 2),
                                      new XElement("lastupdate", new XCData(v.Lastupdate.ToString())),
                                      new XElement("lastmodified", new XCData(v.Lastmodified.ToString())),
                                      new XElement("reindextime", new XCData(v.Reindextime.ToString()))));

                            // Ajout du document dans la alreadydownloaded queue
                            database.AddLinkToAlreadyDownloaded(v.Link);
                            // incrémentation...
                            database.IncrementNumberOfDownload(common.GetDomainFromLink(v.Link));
                        }

                        XElement xml = new XElement("node", items.ToArray());
                        xml.Save(new StringWriter(strb));
                    }
                    else
                    {
                        // On vide la cache de liens à mettre a jour
                        database.FlushAlreadyDowloadedQueue();

                        List<SelectHostResult> result = database.SelectHost(30).ToList();

                        if (result.Count == 0)
                            return null;

                        var x = from i in result
                                select new
                                {
                                    Hqid = i.HQID,
                                    Link = i.LINK,
                                    State = 1,
                                };

                        foreach (var v in x)
                        {
                            items.Add(new XElement("document",
                                      new XElement("url", new XCData(v.Link)),
                                      new XElement("state", v.State)));

                            // Ajout de l'hote dans la waitqueue
                            database.AddHostToWaitQueue(v.Hqid, DateTime.Now);
                            // incrémentation...
                            database.IncrementNumberOfDownload(common.GetDomainFromLink(common.NormalizeLink(v.Link)));
                            // Supression du lien du HostDictionnary
                            database.DeleteHostFromHostDictionnary(v.Link);
                        }

                        XElement xml = new XElement("node", items.ToArray());
                        xml.Save(new StringWriter(strb));
                    }
                    items.Clear();
                }

                return strb.ToString();
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// Change la priotité d'un lien
        /// </summary>
        /// <param name="key">lien</param>
        /// <param name="priority">nouvelle priorité</param>
        [OperationBehavior]
        public void SetPriority(string key, int priority)
        {
            _SetPriority("", new Eventdata() { link = key, priority = priority });
        }

        #endregion




        #region IRemoteOperationsBase Membres

        /// <summary>
        /// Redemarre l'applicatiob
        /// </summary>
        [OperationBehavior]
        public void RestartApplication()
        {
            _RestartApplication("", EventArgs.Empty);
        }

        /// <summary>
        /// Arrete l'application
        /// </summary>
        [OperationBehavior]
        public void StopApplication()
        {
            _StopApplication("", EventArgs.Empty);
        }

        #endregion
    }

    /// <summary>
    /// Class d'evenements
    /// </summary>
    public class Eventdata : EventArgs
    {
        /// <summary>
        /// Priorité d'un lien
        /// </summary>
        public int waitime { get; set; }
        /// <summary>
        /// Lien
        /// </summary>
        public string link { get; set; }
        /// <summary>
        /// Priorité d'un lien
        /// </summary>
        public int priority { get; set; }
        /// <summary>
        /// Contient les données XML des liens à ajouter à la base de données
        /// </summary>
        public string links { get; set; }
    }
}
